package com.pktechan.api.utils;

import com.pktechan.api.exception.CustomException;
import org.apache.commons.beanutils.BeanUtils;

import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 编号生成器,调用静态方法:generate,传递参数即可实现
 *
 * @Description: 根据用户设定的编码规则生成代码，支持日期时间，流水号等
 * <p>时间日期格式:%d{时间日期格式}%,例如:%d{yyyyMMdd}%</p>
 * <p>序列号格式:%s{sequence名称,左侧补零长度}%,例如:%d{seq_order_id,10}%</p>
 * <p>传递参数格式:%参数名称%,例如:%orderId%</p>
 * @Author:
 * @Date: on 2021/03/10 13:33
 */
public class CodeGenerator {

    private static PlaceHolderProcess placeHolderProcess = new DateTimePlaceHolderProcess();
    private static SeqPlaceHolderProcess seqPlaceHolderProcess = new SeqPlaceHolderProcess();
    private static ParamPlaceHolderProcess paramPlaceHolderProcess = new ParamPlaceHolderProcess();

    /**
     * 生成编号的静态方法
     *
     * @param codeRegular 编码生成器的编码字符串
     * @param paramObject 如果编码字符串中定义了参数类型的占位符,这里需要传递Map集合对象
     * @return
     */
    public synchronized static String generate(final String codeRegular, final Object paramObject) {
        //获取所有的参数占位符
        String returnValue = new String(codeRegular);
        returnValue = placeHolderProcess.process(codeRegular, paramObject);
        returnValue = seqPlaceHolderProcess.process(returnValue, paramObject);
        returnValue = paramPlaceHolderProcess.process(returnValue, paramObject);
        return returnValue;
    }


    public static void main(String[] args) {
        String fileText = "日期(年月日):%d{yyyy年MM月dd日}%qq546345日期(年月):%d{yyyy-MM}%45参数7:%7%d参数24:%24%53246序列号:%s{seqAbc,8}%-";
//
//        Pattern p = Pattern.compile("(?<=%d).*?(?=%)");
//        Matcher m = SEQ_PATTERN.matcher(fileText);
//        while (m.find()) {
//            System.out.println(m.group(1));
//        }

//        System.out.println(fileText);
//        fileText = fileText.replaceAll("\\%d\\{yyyymm\\}%", "20170101");
//        System.out.println(fileText);
//        fileText = fileText.replaceAll("\\%d\\{yyyy\\}%", "333344");
//        System.out.println(fileText);

//        ProductEntity productEntity = new ProductEntity();
//        productEntity.setCollectId(new Integer(234234));
//        productEntity.setCurrencyType("currentType");
//        System.out.println(getValueFromObject(productEntity, "collectId"));
//        System.out.println(getValueFromObject(productEntity, "currencyType"));
//        System.out.println(getValueFromObject(productEntity, "c1"));

        Map testMap = new HashMap();
        testMap.put("7", "aaa-value");
        testMap.put("24", "bbb-value");
        PlaceHolderProcess placeHolderProcess = new DateTimePlaceHolderProcess();
        SeqPlaceHolderProcess seqPlaceHolderProcess = new SeqPlaceHolderProcess();
        ParamPlaceHolderProcess paramPlaceHolderProcess = new ParamPlaceHolderProcess();

        fileText = placeHolderProcess.process(fileText, testMap);
        System.out.println(fileText);
        fileText = seqPlaceHolderProcess.process(fileText, testMap);
        System.out.println(fileText);
        System.out.println(paramPlaceHolderProcess.process(fileText, testMap));

    }
}

abstract class PlaceHolderProcess {

    /**
     * 该类的唯一入口方法,对设置了通配符的字符串进行处理,最终替换为实际的字符串
     *
     * @param codeRegular
     * @return
     */
    public String process(final String codeRegular, final Object paramObject) {
        Matcher matcher = getPattern().matcher(codeRegular);
        //这里需要new String,否则会对原有字符串进行修改
        String returnValue = new String(codeRegular);
        Set<String> regularSet = new HashSet<String>();
        while (matcher.find()) {
            regularSet.add(matcher.group(1));
        }
        for (String regular : regularSet) {
            //调用处理占位符的方法,获取到计算结果
            String value = processPlaceHolder(regular, paramObject);
            //TODO　获取了占位符的最终处理值，对传递进来的字符串参数进行替换
            returnValue = replaceRegular(returnValue, regular, value);
        }
        return returnValue;
    }

    /**
     * 对传递进来的字符串参数进行替换
     *
     * @param codeRegular 字符串
     * @param regular     某一个规则的占位符
     * @param value       占位符最终计算的结果值
     * @return
     */
    private String replaceRegular(final String codeRegular, final String regular, final String value) {
        return codeRegular.replaceAll(getReplacePattern(regular), value);
    }

    abstract String processPlaceHolder(final String regular, final Object paramObject);

    abstract Pattern getPattern();

    abstract String getReplacePattern(String regular);
}

/**
 * 日期时间占位符的处理类
 */
class DateTimePlaceHolderProcess extends PlaceHolderProcess {

    //日期时间格式
    private static final Pattern DATETIME_PATTERN = Pattern.compile("\\%d\\{(.*?)\\}%", Pattern.CASE_INSENSITIVE);

    private static final String DATETIME_PATTERN_PREFIX = "\\%d\\{";
    private static final String DATETIME_PATTERN_SURFIX = "\\}%";

    /**
     * 日期时间占位符的具体处理方法
     *
     * @param regular
     * @return
     */
    @Override
    protected String processPlaceHolder(final String regular, final Object paramObject) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(regular);
        return simpleDateFormat.format(new Date());
    }

    @Override
    protected Pattern getPattern() {
        return DATETIME_PATTERN;
    }

    @Override
    protected String getReplacePattern(String regular) {
        return DATETIME_PATTERN_PREFIX + regular + DATETIME_PATTERN_SURFIX;
    }

}

/**
 * 普通参数占位符处理器
 */
class ParamPlaceHolderProcess extends PlaceHolderProcess {

    //普通格式
    private static final Pattern OTHER_PATTERN = Pattern.compile("\\%(.*?)\\%", Pattern.CASE_INSENSITIVE);

    private static final String OTHER_PATTERN_PREFIX = "\\%";
    private static final String OTHER_PATTERN_SURFIX = "\\%";

    /**
     * 参数占位符的具体处理方法
     *
     * @param regular
     * @return
     */
    @Override
    protected String processPlaceHolder(final String regular, final Object paramObject) {
        return getValueFromObject(paramObject, regular);
    }

    @Override
    protected Pattern getPattern() {
        return OTHER_PATTERN;
    }

    @Override
    protected String getReplacePattern(String regular) {
        return OTHER_PATTERN_PREFIX + regular + OTHER_PATTERN_SURFIX;
    }

    /**
     * 从对象中获取制定变量的值
     *
     * @param paramObject
     * @param variableName
     * @return
     * @throws CustomException
     */
    private static String getValueFromObject(final Object paramObject, final String variableName) throws CustomException {

        String returnValue;
        if (paramObject instanceof Map) {
            Map map = (Map) paramObject;
            returnValue = (String) map.get(variableName);
        } else {
            try {
                returnValue = (String) BeanUtils.getProperty(paramObject, variableName);
            } catch (IllegalAccessException lae) {
                throw new CustomException("获取名称为:" + variableName + "参数的值时,产生IllegalAccessException异常.");
            } catch (InvocationTargetException ite) {
                throw new CustomException("获取名称为:" + variableName + "参数的值时,产生InvocationTargetException异常.");
            } catch (NoSuchMethodException nsme) {
                throw new CustomException("没有在对象中找到名称为:" + variableName + "参数的get方法");
            }
        }
        return returnValue;
    }

}


class SeqPlaceHolderProcess extends PlaceHolderProcess {

    //序列号格式
    private static final Pattern SEQ_PATTERN = Pattern.compile("\\%s\\{(.*?)\\}%", Pattern.CASE_INSENSITIVE);

    private static final String SEQ_PATTERN_PREFIX = "\\%s\\{";
    private static final String SEQ_PATTERN_SURFIX = "\\}%";

//    private static SystemService systemService = null;

    /**
     * 参数占位符的具体处理方法
     *
     * @param regular
     * @return
     */
    @Override
    protected String processPlaceHolder(final String regular, final Object paramObject) {
        String[] regularArray = regular.split(",");
        if (regularArray.length != 2) {
            throw new CustomException("参数设置错误：" + regular);
        }
        //TODO 通过Mapper获取Sequence的编号
        synchronized (this) {
//            if (systemService == null) {
//                systemService = (SystemService) SpringContextUtil.getBean("systemService");
//            }
        }

//        Integer sequenceNumber = systemService.selectNextSequenceNumber(regularArray[0]);
        Integer sequenceNumber = 10;

        //

        return StringUtil.fillZero(sequenceNumber.toString(), new Integer(regularArray[1].trim()));
    }

    @Override
    protected Pattern getPattern() {
        return SEQ_PATTERN;
    }

    @Override
    protected String getReplacePattern(String regular) {
        return SEQ_PATTERN_PREFIX + regular + SEQ_PATTERN_SURFIX;
    }
}

